using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.IdentityModel.Tokens;
using webapi.Infrastructure.Cto;
using webapi.Infrastructure.Parameter;

namespace webapi.Infrastructure.Utils
{
    public static class TokenHelper
    {

        /// <summary>
        /// 生成token
        /// </summary>
        /// <param name="tokenParameter">token的配置信息</param>
        /// <param name="username">用户名</param>
        /// <param name="rolename">角色名</param>
        /// <returns></returns>
        public static string GenerateToken(TokenParameter tokenParameter, string username, string rolename)
        {
            var claims = new[]
            {
                new Claim(ClaimTypes.Name,username),
                new Claim(ClaimTypes.Role,rolename)
            };

            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenParameter.Secret));
            var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var securityToken = new JwtSecurityToken(tokenParameter.Issuer, null, claims, expires: DateTime.UtcNow.AddMinutes(tokenParameter.AccessExpiration), signingCredentials: credentials);

            //生成token
            var token = new JwtSecurityTokenHandler().WriteToken(securityToken);

            return token;
        }

        /// <summary>
        /// 刷新token
        /// </summary>
        /// <param name="accessToken">快过期或已经过期的token</param>
        /// <param name="tokenParameter">token配置信息</param>
        /// <returns></returns>
        public static AccessTokenCto RefreshToken(string accessToken, TokenParameter tokenParameter)
        {
            // 以下为演示代码，没有加任何判断和验证，请勿直接用于生产环境!!!

            //这儿是验证Token的代码
            var handler = new JwtSecurityTokenHandler();

            ClaimsPrincipal claim = handler.ValidateToken(accessToken, new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenParameter.Secret)),
                ValidateIssuer = false,
                ValidateAudience = false,
                ValidateLifetime = false,
            }, out SecurityToken securityToken);
            var username = claim.Identity.Name;
            
            //这儿是生成Token的代码
            var token = GenerateToken(tokenParameter, username, "超级孙猴子");

            //此处的RefreshToken是直接指定的字符串，在正式项目中，应该是一个可验证的加密串，如md5、hash等
            var refreshToken = "654321";

            return new AccessTokenCto
            {
                AccessToken = token,
                RefreshToken = refreshToken
            };

        }
    }
}